package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"
	"log"
	"time"
)

type Scheduling struct {
	Id int64
	SchedulingDate string
	StaffId int64
	StaffName string
	CreatedAt time.Time
	UpdatedAt time.Time
}

var x *xorm.Engine

func init(){
	var xErr error
	x, xErr = xorm.NewEngine("mysql", "root:new_password@tcp(127.0.0.1:3306)/scheduling?charset=utf8")
	if xErr != nil {
		log.Fatal("数据库连接失败:", xErr)
	}
	if err := x.Sync2(new(Scheduling)); err != nil {
		log.Fatal("数据表同步失败:", err)
	}
}

func CalculateLeaveTime(st time.Time, et time.Time, work string, closing string, noonBreak string, afternoonWork string, staffId int64) float64{

	loadLocation, _ := time.LoadLocation("Asia/Shanghai")

	workShift, _ := time.ParseInLocation("2006-01-02 15:04:05", et.Format("2006-01-02")+" "+work, loadLocation)
	closingTime, _ := time.ParseInLocation("2006-01-02 15:04:05", st.Format("2006-01-02")+" "+closing, loadLocation)

	noonBreakTime, _ := time.ParseInLocation("2006-01-02 15:04:05", st.Format("2006-01-02")+" "+noonBreak, loadLocation)
	afternoonWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", et.Format("2006-01-02")+" "+afternoonWork, loadLocation)

	startTime, _ := time.ParseInLocation("2006-01-02", st.Format("2006-01-02"), loadLocation)
	endTime, _ := time.ParseInLocation("2006-01-02", et.Format("2006-01-02"), loadLocation)

	day := 0
	var dateList []time.Time
	dateList = append(dateList, startTime)
	for {
		if startTime.Unix() >= endTime.Unix(){
			break
		}
		
		day += 1

		t := startTime.AddDate(0, 0, 1)
		dateList = append(dateList, t)

		startTime = startTime.AddDate(0, 0, 1)
	}

	fmt.Println("day：", day)
	fmt.Println("dateList：", dateList)

	var leaveTime float64

	startAfternoonWorkTime, _ := time.ParseInLocation("2006-01-02 15:04:05", st.Format("2006-01-02")+" "+afternoonWork, loadLocation)
	endNoonBreakTime, _ := time.ParseInLocation("2006-01-02 15:04:05", et.Format("2006-01-02")+" "+noonBreak, loadLocation)

	if day == 0{

		if st.After(noonBreakTime) == true && st.Before(startAfternoonWorkTime){
			st = startAfternoonWorkTime
		}

		if et.After(endNoonBreakTime) == true && et.Before(afternoonWorkTime) == true{
			et = endNoonBreakTime
		}

		if st.After(noonBreakTime) == true && et.Before(afternoonWorkTime){
			return 0
		}

		if st.Before(noonBreakTime) == true && et.After(afternoonWorkTime) == true{
			leaveTime = float64(et.Unix() - st.Unix())/3600 - 1.5
		}else {
			leaveTime = float64(et.Unix() - st.Unix())/3600
		}

		var scheduling Scheduling
		x.Where("scheduling_date = ?", startTime.Format("2006-01-02")).And("staff_id = ?", staffId).Get(&scheduling)
		if scheduling.Id == 0{
			leaveTime = 0
		}
		
	}else if day >= 1{

		if st.After(noonBreakTime) == true && st.Before(startAfternoonWorkTime) == true{
			st = startAfternoonWorkTime
		}

		if et.After(endNoonBreakTime) == true && et.Before(afternoonWorkTime) == true{
			et = endNoonBreakTime
		}

		var startLeaveTime float64
		var endLeaveTime float64

		if st.Before(noonBreakTime) == true{
			startLeaveTime = float64(closingTime.Unix() - st.Unix())/3600 - 1.5
		}else{
			startLeaveTime = float64(closingTime.Unix() - st.Unix())/3600
		}

		if et.After(afternoonWorkTime) == true{
			endLeaveTime = float64(et.Unix() - workShift.Unix())/3600 - 1.5
		}else {
			endLeaveTime = float64(et.Unix() - workShift.Unix())/3600
		}

		fmt.Println("startLeaveTime：", startLeaveTime)
		fmt.Println("endLeaveTime：", endLeaveTime)

		leaveTime = startLeaveTime + endLeaveTime + float64((day-1))*7.5

		var startScheduling Scheduling
		x.Where("scheduling_date = ?", dateList[0].Format("2006-01-02")).And("staff_id = ?", staffId).Get(&startScheduling)
		if startScheduling.Id == 0{
			leaveTime -= startLeaveTime
		}

		var endScheduling Scheduling
		x.Where("scheduling_date = ?", dateList[len(dateList)-1].Format("2006-01-02")).And("staff_id = ?", staffId).Get(&endScheduling)
		if endScheduling.Id == 0{
			leaveTime -= endLeaveTime
		}

		fmt.Println("dateList[1:len(dateList)-2]：", dateList[1:len(dateList)-1])
		for _, date := range dateList[1:len(dateList)-1]{
			var scheduling Scheduling
			x.Where("scheduling_date = ?", date.Format("2006-01-02")).And("staff_id = ?", staffId).Get(&scheduling)
			if scheduling.Id == 0{
				leaveTime -= 7.5
			}
		}
		
	}

	return leaveTime
}

func CalculateOptionalTimePeriod(work string, closing string, noonBreak string, afternoonWork string, startOrEnd int) []string{
	
	loadLocation, _ := time.LoadLocation("Asia/Shanghai")
	workShift, _ := time.ParseInLocation("15:04:05", work, loadLocation)
	closingTime, _ := time.ParseInLocation("15:04:05", closing, loadLocation)
	noonBreakTime, _ := time.ParseInLocation("15:04:05", noonBreak, loadLocation)
	afternoonWorkTime, _ := time.ParseInLocation("15:04:05", afternoonWork, loadLocation)

	var timePeriod []string

	if startOrEnd == 1{
		timePeriod = append(timePeriod, work)
	}

	m, _ := time.ParseDuration("30m")

	for {
		workShift = workShift.Add(m)

		if 	workShift.Unix() >= noonBreakTime.Unix(){
			break
		}

		timePeriod = append(timePeriod, workShift.Format("15:04:05"))
	}

	if startOrEnd == 1{
		timePeriod = append(timePeriod, afternoonWork)
	}else {
		timePeriod = append(timePeriod, noonBreak)
	}

	for {
		afternoonWorkTime = afternoonWorkTime.Add(m)

		if 	afternoonWorkTime.Unix() >= closingTime.Unix(){
			break
		}

		timePeriod = append(timePeriod, afternoonWorkTime.Format("15:04:05"))
	}

	if startOrEnd == 2{
		timePeriod = append(timePeriod, closing)
	}

	return timePeriod
}

func main(){

	loadLocation, _ := time.LoadLocation("Asia/Shanghai")
	st, _ := time.ParseInLocation("2006-01-02 15:04:05", "2020-11-07 10:00:00", loadLocation)
	et, _ := time.ParseInLocation("2006-01-02 15:04:05", "2020-11-11 11:30:00", loadLocation)

	fmt.Println("请假时长：", CalculateLeaveTime(st, et, "09:00:00", "18:00:00", "12:00:00", "13:30:00", 342404652458835968))

	fmt.Println("开始请假时间，可选时间段：", CalculateOptionalTimePeriod("09:00:00", "18:00:00", "12:00:00", "13:30:00", 1))
	fmt.Println("结束请假时间，可选时间段：", CalculateOptionalTimePeriod("09:00:00", "18:00:00", "12:00:00", "13:30:00", 2))

}
